package plugins

import (
	"encoding/json"
	"errors"
	"fmt"
	"gadmin/log"
	"gadmin/model"
)

type Plugin interface {
	Run() error
}

type BasePlugin struct {
	Index int
	Steps []model.StepHistory
}

func (self *BasePlugin) RenderParams() (data map[string]interface{}) {
	data = make(map[string]interface{})
	for key, value := range self.Steps {
		if key < self.Index {
			// 其他节点
			objResult := make(map[string]interface{})
			err := json.Unmarshal([]byte(value.Output), &objResult)
			if err == nil {
				for rk, rv := range objResult {
					data[fmt.Sprintf("%s_%s", value.Name, rk)] = rv
				}
			} else {
				log.Logger.Info("输出不是JSON，跳过")
			}
		} else {
			return data
		}
	}
	return data
}

func (self *BasePlugin) UpdateOutput(output string) {
	self.Steps[self.Index].Output = output
	err := model.DB.Save(self.Steps[self.Index]).Error
	if err != nil {
		panic(err)
	}
}

func (self *BasePlugin) UpdateErrOutput(output string) {
	self.Steps[self.Index].ErrOutput = output
	err := model.DB.Save(self.Steps[self.Index]).Error
	if err != nil {
		panic(err)
	}
}

func (self *BasePlugin) UpdateInput(input string) {
	self.Steps[self.Index].Input = input
	err := model.DB.Save(self.Steps[self.Index]).Error
	if err != nil {
		panic(err)
	}
}

func (self *BasePlugin) UpdateStatus(status string) {
	self.Steps[self.Index].Status = status
	err := model.DB.Save(self.Steps[self.Index]).Error
	if err != nil {
		panic(err)
	}
}

func (self *BasePlugin) Running() {
	self.UpdateStatus("running")
}

func (self *BasePlugin) Finish() {
	self.UpdateStatus("finish")
}

func (self *BasePlugin) Error() {
	self.UpdateStatus("error")
}

func RunPlugin(index int, steps []model.StepHistory) (err error) {
	var p Plugin
	step := steps[index]
	switch step.Type {
	case "start":
		p = &StartPlugin{BasePlugin: BasePlugin{Index: index, Steps: steps}}
	case "end":
		p = &EndPlugin{BasePlugin{Index: index, Steps: steps}}
	case "shell":
		p = &ShellPlugin{BasePlugin{Index: index, Steps: steps}}
	case "python":
		p = &PythonPlugin{BasePlugin{Index: index, Steps: steps}}
	default:
		panic(errors.New("工作流未知类型的步骤"))
	}
	return p.Run()
}
